package com.shi.shiro.filter;

import com.shi.shiro.common.Constants;
import com.shi.shiro.common.Response;
import com.shi.shiro.common.Result;
import com.shi.shiro.common.UserHolder;
import com.shi.shiro.domain.User;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class LoginCheckFilter extends AccessControlFilter {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        HttpServletRequest req = (HttpServletRequest) request;
        String requestURI = req.getRequestURI();
        log.info("过滤器 isAccessAllowed()");
        log.info("请求uri: {}",requestURI);
        // 需要放行的请求
        for (String path : Constants.NOT_REQUIRED_AUTHENTICATION_PATH) {
            if (path.equals(requestURI)){
                return true;
            }
        }
        // 检查是否有 token
        String authorization = req.getHeader("Authorization");
        // 如果没有token就直接放行，如：/login
        if (!StringUtils.hasText(authorization)){
            return false;
        }
        User userInfo = (User) redisTemplate.opsForValue().get(authorization);
        // 如果缓存中有用户的信息，说明已经登陆过，放行
        if (ObjectUtils.isEmpty(userInfo)) {
            return false;
        }
        log.info("用户已登录过,可放行. userInfo: {} ",userInfo);
        // 校验通过的用户信息存入 UserHolder
        Long expire = redisTemplate.getExpire(authorization, TimeUnit.MINUTES);
        log.info("token剩余过期时间: {} 分",expire);
        if (expire<=5){
            redisTemplate.expire(authorization,30,TimeUnit.MINUTES);
            log.info("修改过期时间");
        }
        UserHolder.setUser((User) userInfo);
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        Response.write((HttpServletResponse) response, Result.fail("用户未登录，访问被拒绝"));
        return true;
    }

}